use bytes::{Bytes, BytesMut};
use core::str;
use std::{fmt::Display, ops::Deref};
use tools::{
	error::buf_err::FromBufError,
	types::bufs::{FromBuf, ToBuf},
	utils::byte::{split_on, str_from_utf8_bytes},
};

use crate::untils::borrow::StrPtr;

pub(crate) const CALL_ID: &'static [u8] = b"Call-ID";
pub(crate) const FROM: &'static [u8] = b"From";
pub(crate) const TO: &'static [u8] = b"To";
pub(crate) const VIA: &'static [u8] = b"Via";
pub(crate) const ROUTE: &'static [u8] = b"Route";
pub(crate) const RECORD_ROUTE: &'static [u8] = b"Record-Route";
pub(crate) const CONTACT: &'static [u8] = b"Contact";
pub(crate) const MAX_FORWARDS: &'static [u8] = b"Max-Forwards";
pub(crate) const CONTENT_LENGTH: &'static [u8] = b"Content-Length";
pub(crate) const CONTENT_TYPE: &'static [u8] = b"Content-Type";
pub(crate) const SUPPORTED: &'static [u8] = b"Supported";
pub(crate) const ALLOW: &'static [u8] = b"Allow";
pub(crate) const ALLOW_EVENTS: &'static [u8] = b"Allow-Events";
pub(crate) const EXPIRES: &'static [u8] = b"Expires";
pub(crate) const CSEQ: &'static [u8] = b"CSeq";
pub(crate) const SESSION_EXPIRES: &'static [u8] = b"Session-Expires";
pub(crate) const MIN_SE: &'static [u8] = b"Min-SE";
pub(crate) const P_ASSERTED_IDENTITY: &'static [u8] = b"P-Asserted-Identity";
pub(crate) const P_EARLY_MEDIA: &'static [u8] = b"P-Early-Media";
pub(crate) const REMOTE_PARTY_ID: &'static [u8] = b"Remote-Party-ID";
pub(crate) const USER_AGENT: &'static [u8] = b"User-Agent";
pub(crate) const WWW_AUTHENTICATE: &'static [u8] = b"WWW-Authenticate";
pub(crate) const AUTHORIZATION: &'static [u8] = b"Authorization";
pub(crate) const REQUIRE: &'static [u8] = b"Require";
pub(crate) const REASON: &'static [u8] = b"Reason";
pub(crate) const RETRY_AFTER: &'static [u8] = b"Retry-After";

///sip的头字段名.
#[derive(Debug, Eq, Clone, PartialEq, PartialOrd, Ord)]
pub enum HeaderName {
	CallID,
	From,
	To,
	Via,
	Route,
	RecordRoute,
	Contact,
	MaxForwards,
	ContentLength,
	ContentType,
	Supported,
	Allow,
	AllowEvents,
	Expires,
	CSeq,
	SessionExpires,
	MinSE,
	PAssertedIdentity,
	PEarlyMedia,
	RemotePartyID,
	UserAgent,
	WWWAuthenticate,
	Authorization,
	Require,
	Reason,
	RetryAfter,
	Other,
}

impl Display for HeaderName {
	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
		f.write_str(str_from_utf8_bytes(self.as_ref()))
	}
}

impl ToBuf for HeaderName {
	type Target = BytesMut;

	#[inline]
	fn write_to(&self, target: &mut Self::Target) -> Result<(), tools::error::buf_err::ToBufError> {
		target.extend_from_slice(self.as_ref());

		Ok(())
	}
}

impl AsRef<[u8]> for HeaderName {
	fn as_ref(&self) -> &[u8] {
		match self {
			HeaderName::CallID => CALL_ID,
			HeaderName::From => FROM,
			HeaderName::To => TO,
			HeaderName::Via => VIA,
			HeaderName::Route => ROUTE,
			HeaderName::RecordRoute => RECORD_ROUTE,
			HeaderName::Contact => CONTACT,
			HeaderName::MaxForwards => MAX_FORWARDS,
			HeaderName::ContentLength => CONTENT_LENGTH,
			HeaderName::ContentType => CONTENT_TYPE,
			HeaderName::Supported => SUPPORTED,
			HeaderName::Allow => ALLOW,
			HeaderName::AllowEvents => ALLOW_EVENTS,
			HeaderName::Expires => EXPIRES,
			HeaderName::CSeq => CSEQ,
			HeaderName::SessionExpires => SESSION_EXPIRES,
			HeaderName::MinSE => MIN_SE,
			HeaderName::PAssertedIdentity => P_ASSERTED_IDENTITY,
			HeaderName::PEarlyMedia => P_EARLY_MEDIA,
			HeaderName::RemotePartyID => REMOTE_PARTY_ID,
			HeaderName::UserAgent => USER_AGENT,
			HeaderName::WWWAuthenticate => WWW_AUTHENTICATE,
			HeaderName::Authorization => AUTHORIZATION,
			HeaderName::Require => REQUIRE,
			HeaderName::Reason => REASON,
			HeaderName::RetryAfter => RETRY_AFTER,
			HeaderName::Other => b"",
		}
	}
}

impl HeaderName {
	pub(crate) fn from_buf_all(from: &[u8]) -> Result<Self, FromBufError>
	where
		Self: Sized,
	{
		Ok(match from {
			CALL_ID => HeaderName::CallID,
			FROM => HeaderName::From,
			TO => HeaderName::To,
			VIA => HeaderName::Via,
			ROUTE => HeaderName::Route,
			RECORD_ROUTE => HeaderName::RecordRoute,
			CONTACT => HeaderName::Contact,
			MAX_FORWARDS => HeaderName::MaxForwards,
			CONTENT_LENGTH => HeaderName::ContentLength,
			CONTENT_TYPE => HeaderName::ContentType,
			SUPPORTED => HeaderName::Supported,
			ALLOW => HeaderName::Allow,
			ALLOW_EVENTS => HeaderName::AllowEvents,
			EXPIRES => HeaderName::Expires,
			CSEQ => HeaderName::CSeq,
			SESSION_EXPIRES => HeaderName::SessionExpires,
			MIN_SE => HeaderName::MinSE,
			P_ASSERTED_IDENTITY => HeaderName::PAssertedIdentity,
			P_EARLY_MEDIA => HeaderName::PEarlyMedia,
			REMOTE_PARTY_ID => HeaderName::RemotePartyID,
			USER_AGENT => HeaderName::UserAgent,
			WWW_AUTHENTICATE => HeaderName::WWWAuthenticate,
			AUTHORIZATION => HeaderName::Authorization,
			REQUIRE => HeaderName::Require,
			REASON => HeaderName::Reason,
			RETRY_AFTER => HeaderName::RetryAfter,
			_ => HeaderName::Other,
		})
	}
}

#[derive(Debug, Eq, PartialEq, PartialOrd, Ord, Clone)]
pub struct CustHeaderName {
	inner: StrPtr,
}

impl ToBuf for CustHeaderName {
	type Target = BytesMut;

	#[inline]
	fn write_to(&self, target: &mut Self::Target) -> Result<(), tools::error::buf_err::ToBufError> {
		target.extend_from_slice(self.inner.as_bytes());
		Ok(())
	}
}
impl Deref for CustHeaderName {
	type Target = str;

	fn deref(&self) -> &Self::Target {
		self.inner.as_str()
	}
}

impl FromBuf for CustHeaderName {
	type From = Bytes;

	fn from_buf_all(from: Self::From) -> Result<Self, FromBufError>
	where
		Self: Sized,
	{
		//确定传入的一定是一个utf8的内容.
		Ok(CustHeaderName {
			inner: StrPtr::from_bytes(&from),
		})
	}

	fn from_buf(from: &mut Self::From) -> Result<Self, FromBufError>
	where
		Self: Sized,
	{
		let buf = split_on(from, b':');
		Self::from_buf_all(buf)
	}
}
